package vrann.dataformats.json;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class JsonHash extends JsonElement 
{
	private Map<String, JsonElement> values = new HashMap<String, JsonElement>();
	
	private List<String> orderIndex = new ArrayList<String>();
	
	public Map getValues()
	{
		return values;
	}
	
	public void put(String key, JsonElement value)
	{
		values.put(key, value);
		orderIndex.add(key);
	}
	
	public String toString() {
		StringBuffer arrayParts = new StringBuffer();
		arrayParts.append("{");
		Iterator<String> indexIterator = orderIndex.iterator();
		while (indexIterator.hasNext()) {
			String key = indexIterator.next();
			String currentHashString = "\"" + key + "\"" + ":" + values.get(key).getEscapedString();			
			if (indexIterator.hasNext()) {
				currentHashString += ",";
			}
			arrayParts.append(currentHashString);
		}
		arrayParts.append("}");
		return arrayParts.toString();
	}
	
	public String getEscapedString()
	{
		return toString();
	}
	
	protected static boolean isKeyValid(String key)
	{
		if(key.matches("[a-zA-Z0-9]*")) {
			return true;
		}
		return false;
	}
	
	public static JsonHash initFromString(String input) throws Exception
	{
		if (input.matches("\\{.*\\}")) {
			JsonHash resultHash = new JsonHash();
			String newInput = input.substring(1, input.length() - 1);		
			String[] keyValuePairs = newInput.split(",");
			for (int i = 0; i < keyValuePairs.length; i++) {
				String[] keyValuePair = keyValuePairs[i].trim().split(":", 2);
				if (keyValuePair.length < 2) {
					throw new Exception("String is not valid JSON Hash");
				}
				String key = keyValuePair[0].trim().replaceAll("\"", "");
				String value = keyValuePair[1].trim();
				
				Character brace = 'N';
				Character rightBrace = 'N';
				if (value.startsWith("[")) {
					brace = '[';
					rightBrace = ']';
				} else if (value.startsWith("{")) {
					brace = '{';
					rightBrace = '}';
				}
				
				if (!brace.equals('N')) {
					int leftBraceCount = countBraceOccurancies(value, brace);
					int rightBraceCount = 0;
					while(rightBraceCount < leftBraceCount) {
						i++;
						leftBraceCount += countBraceOccurancies(keyValuePairs[i], brace);
						rightBraceCount += countBraceOccurancies(keyValuePairs[i], rightBrace);
						value += ", " + keyValuePairs[i];
					}	
				}

				if (isKeyValid(key)) {
					try {
						JsonElement valueElement = JsonElement.initFromString(value);						
						resultHash.put(key, valueElement);
					} catch (Exception e) {
						throw new Exception("String contains invalid JSON elements");
					}
				} else {
					throw new Exception("JSON Hash has invalid keys");			
				}
			}
			return resultHash;
		} else {
			throw new Exception("String is supposed to have format {.*}");			
		}
	}
}
